
package hasthi.metamodel;

import static hasthi.common.constants.HasthiConstants.LOGGER_NAME;
import hasthi.common.ChangeListener;
import hasthi.common.HasthiException;
import hasthi.common.InvaliedResourceDataException;
import hasthi.common.HasthiException.FaultCode;
import hasthi.manager.ManagedResourceType;
import hasthi.metamodel.resource.AbstractResourceModel;
import hasthi.metamodel.resource.EditableManagedResource;
import hasthi.metamodel.resource.ResourceModelContext;

import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.xml.namespace.QName;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Maintained a Summery of resources managed by remote managers. Usually this is held by the coordinator
 * @author Srinath Perera(hperera@cs.indiana.edu)
 */


public class SummerizedResourceModel extends AbstractResourceModel{
    private static Log log = LogFactory.getLog(LOGGER_NAME);
    
    protected Map<QName,EditableManagedResource> localResourceRepository = new ConcurrentHashMap<QName, EditableManagedResource>();
    public SummerizedResourceModel(ResourceModelContext context) throws HasthiException {
        super(context);
    }

    public EditableManagedResource addNewResource(QName resourceName,String managerAgentURL, String category, String userDefinedType) throws InvaliedResourceDataException, HasthiException{
        EditableManagedResource resource = createNewResource(Placement.Summerized,resourceName,managerAgentURL,category,userDefinedType);
        localResourceRepository.put(resourceName, resource);
        ChangeListener modelListener = context.getChangeListener();
        if(modelListener != null){
            modelListener.resourceAdded(resource.getQName());    
        }
        return resource;
    }
    
    public EditableManagedResource addNewResource(QName resourceName,ManagedResourceType resourceData) throws InvaliedResourceDataException, HasthiException{
        EditableManagedResource resource = super.createNewResource(Placement.Summerized, resourceData);
        localResourceRepository.put(resourceName, resource);
        ChangeListener modelListener = context.getChangeListener();
        if(modelListener != null){
            modelListener.resourceAdded(resource.getQName());    
        }
        return resource;
    }

    
    public EditableManagedResource removeResource(QName resourceName) throws HasthiException{
        if(localResourceRepository.containsKey(resourceName)){
            EditableManagedResource resource =  localResourceRepository.remove(resourceName);
            ChangeListener modelListener = context.getChangeListener();
            if(modelListener != null){
                modelListener.resourceRemoved(resource.getQName());    
            }
            log.info("Removed resource "+ resourceName + " from the meta model");
            return resource;
        }else{
            throw new HasthiException("remove resource is only defined for local copies", FaultCode.InvaliedLocalArgumnet);
        }
    }
    
    public EditableManagedResource getResource(QName name) throws HasthiException{
        EditableManagedResource resource = localResourceRepository.get(name);
        if(resource != null){
            return resource;
        }else{
            return null;
//            RemoteManagerContext remoteManager = context.getCoordinatorContext().getManagerForResource(name); 
//            
//            if(remoteManager == null || remoteManager.getAddress() == null){
//                return null;
//            }
//            String holderURL = remoteManager.getAddress().getSoapAddress();
//            return fetchRemoteResource(holderURL, name,true);
        }
    }
    
    /**
     * Only return local copies
     * @return
     */
    public Collection<QName> getResources(){
        return localResourceRepository.keySet();
    }
}


